extends Node2D

@onready var board_tile_map: TileMapLayer = $"BoardTileMap"
@onready var 状态label = %"状态Label"

#region 棋盘坐标相关
const 坐标字典:Dictionary={a=0,b=1,c=2,d=3,e=4,f=5,g=6,h=7,i=8}
const 字符坐标:String="abcdefghi"
const 棋盘max行:int=10
const 棋盘max列:int=9
#endregion

#region 棋局信息
var 当前棋子:棋子类=null
var	红方行动:bool=false:
	set(value):
		红方行动=value
		if 红方行动:
			显示状态("红方行动")
		else:
			显示状态("黑方行动")
		
var moves:Array=[]
var 总步数:int=0
var 当前回合数:int:
	get():
		return 总步数/2+1			
var 回合上限:int=-1

var 棋局FEN:String				#含moves信息
var 未吃子棋局FEN:String			#不含moves信息

var 棋子棋局:Array=[]:			#实际棋局, 供棋子判断能否吃子/将军等判断
	get():
		return 获取棋子棋局()
#endregion		

func 初始化棋局数据():
	红方行动=false
	moves.clear()
	总步数=0
	棋局FEN=""
	未吃子棋局FEN=""
	
func 初始化棋局(棋谱数据:棋谱数据类):
	初始化棋局数据()
	载入棋局(棋谱数据)
		
func 载入棋局(棋谱数据:棋谱数据类):
	回合上限=棋谱数据.红最长
	载入FEN棋谱(棋谱数据.红先棋局)
	
func 载入FEN棋谱(棋谱:String):
	var 棋谱信息=棋谱.split(" ")
	var 棋子布局:String=棋谱信息[0]
	红方行动=(棋谱信息[1]=="w")
	var 字符棋局=棋谱转字符棋局(棋子布局)
	for 棋子 in board_tile_map.get_children():
		board_tile_map.remove_child(棋子)
		棋子.queue_free()
	for y in range(棋盘max行):
		for x in range(棋盘max列):
			if 字符棋局[y][x]!=null:
				var 棋子:棋子类=GameGlobal.FEN棋类[字符棋局[y][x]].instantiate()
				board_tile_map.add_child(棋子)	
				初始化棋子到pos(棋子,Vector2i(y,x))
	执行FEN中moves(棋谱)	
#endregion	
				
#region 指令获取  指令/坐标转换
#move指令为4位, 格式为g2h2
func 获取move指令(line:String):
	return line.left(13).right(4)

#指令为2位, 格式为g2
func 获取指令棋子(指令:String):
	var pos=获取指令坐标(指令)
	return 获取pos棋子(pos)	
	
#指令为2位, 格式为g2
func 获取指令坐标(指令:String):
	return Vector2i(9-int(指令[1]),坐标字典[指令[0]])
	
#指令为2位, 格式为g2	
func 坐标转指令(坐标:Vector2i):
	var 行:String=str(9-坐标.x)
	var 列:String=字符坐标[坐标.y]
	return  列+行
#endregion
		
#region 棋子初始化/移动相关	
func 初始化棋子到pos(棋子:棋子类,pos:Vector2i):
	棋子.pos=pos
	棋子.position=board_tile_map.map_to_local(Vector2i(pos.y,pos.x))		
	
#与移动棋子的区别是没有动画效果, 执行moves里的指令用
func 设置棋子到pos(棋子:棋子类,pos:Vector2i):
	红方行动=!红方行动
	棋子.position=board_tile_map.map_to_local(Vector2i(pos.y,pos.x))
	棋子落子(棋子,pos)
	
func 棋子落子(棋子:棋子类,pos:Vector2i):
	if 可以吃子(pos):
		吃子(pos)
		moves.clear()
		棋子.pos=pos
		刷新吃子时棋局FEN()
	else:
		var move:String=坐标转指令(棋子.pos)+坐标转指令(pos)
		moves.append(move)
		刷新吃子后棋局FEN()
		棋子.pos=pos	
		
func 执行move指令(指令:String):
	var 棋子:棋子类=获取指令棋子(指令.left(2))
	var pos:Vector2i=获取指令坐标(指令.right(2))
	设置棋子到pos(棋子,pos)
		
func 执行FEN中moves(FEN:String):
	moves.clear()
	var FEN中moves=获取FEN中moves(FEN)
	if FEN中moves.is_empty():
		刷新吃子时棋局FEN()
	else:
		未吃子棋局FEN=获取FEN中棋局(FEN)
		for move in FEN中moves:
			执行move指令(move)
				
func 可以吃子(pos:Vector2i)	:
	var pos棋子:棋子类=获取pos棋子(pos)
	if pos棋子!=null:
		return true
	return false		

func 吃子(pos:Vector2i):
	GameGlobal.播放吃子音效()
	var pos棋子:棋子类=获取pos棋子(pos)
	board_tile_map.remove_child(pos棋子)
	pos棋子.queue_free()	

func 获取pos棋子(pos:Vector2i):
	return 棋子棋局[pos.x][pos.y]
	
func 刷新吃子时棋局FEN():
	未吃子棋局FEN=获取棋局FEN()
	棋局FEN=未吃子棋局FEN
	
func 刷新吃子后棋局FEN():
	棋局FEN=未吃子棋局FEN+获取moves字符串()	
#endregion

#region 刷新UI
func 显示状态(状态:String):
	if 红方行动:
		状态label.self_modulate=Color.DARK_RED
	else:
		状态label.self_modulate=Color.BLACK
	状态label.text=状态	
#endregion

#region 棋局/FEN相关
func 获取棋局FEN()->String:
	var FEN:String=""
	var 字符棋局=获取字符棋局()
	for y in range(棋盘max行):
		var 可累加:bool=true
		var 空num:int=0
		if y>0:
			FEN+="/"
		for x in range(棋盘max列):
			var ch=字符棋局[y][x]
			if ch==null:
				可累加=true
				空num+=1
			else:
				if 空num>0:
					FEN+=str(空num)
				空num=0
				可累加=false
				FEN+=字符棋局[y][x]
			if x==棋盘max列-1 and 可累加: 
				FEN+=str(空num)
	var 当前方="b"
	if 红方行动:	当前方="w"		
	FEN+=" "+当前方+" - - 0 "+str(当前回合数)
	return FEN	

func 获取字符棋局():
	var _字符棋局=获取空棋局()
	for 棋子 in board_tile_map.get_children():
		var pos=棋子.pos
		_字符棋局[pos.x][pos.y]=棋子.ID
	return _字符棋局
	
func 获取棋子棋局():
	var _棋子棋局=获取空棋局()
	for 棋子 in board_tile_map.get_children():
		var pos=棋子.pos
		_棋子棋局[pos.x][pos.y]=棋子
	return _棋子棋局
	
func 棋谱转字符棋局(布局:String):
	var 字符棋局=获取空棋局()
	var now_x:int=0
	var now_y:int=0
	for ch in 布局:
		if ch>"0" and ch <="9":
			now_x+=int(ch)
		elif ch=="/":
			now_y+=1
			now_x=0
		else:
			字符棋局[now_y][now_x]=ch
			now_x+=1
	return 字符棋局
	
func 获取空棋局():
	var 空棋局棋子集:Array=[]
	for i in range(棋盘max行):
		var 一行:Array=[]
		一行.resize(棋盘max列)
		空棋局棋子集.append(一行)
	return 空棋局棋子集
	
func 获取moves字符串():
	var str_moves:String=" moves"
	for move in moves:
		str_moves+=(" "+move)
	return str_moves
	
func 获取FEN中moves(FEN:String):
	var FEN中moves:Array=[]
	var 指令集:Array=FEN.split(" ")
	var moves_index:int=指令集.find("moves")
	if moves_index!=-1:
		for index in range(moves_index+1,指令集.size()):
			FEN中moves.append(指令集[index])	
	return FEN中moves
	
func 获取FEN中棋局(FEN:String):
	var moves_index:int=FEN.find(" moves")
	if moves_index!=-1:
		return FEN.left(moves_index)
	return FEN
#endregion
